var updateDSOInrterval = 500;
function loadDSOs(parent,sync){
	var oInputs = getElementsByName(new Array("input","textarea","table"));
	for( e in oInputs )
		if( (oInputs[e].dataFld || oInputs[e].dataSrc) )
			oInputs[e].onkeyup = onInputKeyPress;
	var e,eDSOs = getElementsByName("OBJECT");
	for( e in eDSOs )
		if( !eDSOs[e].noLoad )loadDSO(eDSOs[e],null,sync);
	return;
	var eDSOs = new Enumerator((parent || document).all.tags("OBJECT"));
	for( ; !eDSOs.atEnd(); eDSOs.moveNext() )
		if( !eDSOs.item().noLoad )loadDSO(eDSOs.item(),null,sync);
}
function initDSOs(urlInFunc,urlOutFunc,parentElement){
	var eDSOs = new Enumerator((parentElement || document).all.tags("OBJECT")),dso;
	for( ; !eDSOs.atEnd(); eDSOs.moveNext() ){
		dso = eDSOs.item();
			dso.outerHTML = dso.outerHTML.replace(/></,makeUrl(dso,"urlIn",urlInFunc)+makeUrl(dso,"urlOut",urlOutFunc)+" dirty=''><");
	}
	// Locals
	function makeUrl(dso,url,func){		return  dso[url] ? "" : " "+url+"=\""+func(dso)+"\"";	}
}
var oUpdateDSOs = {};
function updateDSOEx(el,thread){
	var dataSrcStr = getDataSrc(el);
	var dataSrc = eval(dataSrcStr);
	if( !thread ){
		setDirtyStatus(dataSrc,1);
		clearTimeout(oUpdateDSOs[dataSrcStr]);
		return oUpdateDSOs[dataSrcStr] = setTimeout("updateDSOEx(document.all['"+el.uniqueID+"'],true)",updateDSOInrterval);
	}
	clearTimeout(oUpdateDSOs[dataSrcStr]);	oUpdateDSOs[dataSrcStr] = null;
	if( thread == 'clear' )return ;
	dataSrc.URL = dataSrc.urlOut;
	if( dataSrc.URL.indexOf("/")==0 )dataSrc.URL = getScriptServer()+dataSrc.URL;
	try{
//alert("updateDSOEx('"+dataSrcStr+"')");
		setDirtyStatus(dataSrc);
		dataSrc.SubmitChanges();
		dataSrc.CancelUpdate();
		if( typeof(dataSrc.rowInserted) == 'undefined' )return;
		if( dataSrc.rowInserted == 1)loadDSO(el);
		dataSrc.rowInserted = 0;
	}catch(e){return alert("SubmitChanges("+dataSrcStr+")\n"+unescape(e.description))}
}
function rsToString(rs){
	var strm = new ActiveXObject("ADODB.Stream");
	strm.Type = adTypeText = 2;
	strm.Open();
	rs.Save(strm,adPersistXML = 1);
	return strm.ReadText(-1);
}
function getRSFromString(rsString,stringFieldSizes){
	if( !rsString )return emptyRS();
	var re = /<s:AttributeType [^>]+>/g;
	var aAttrs = rsString.match(/<s:AttributeType [^>]+>/gi);
	var xml = new ActiveXObject("Microsoft.XMLDOM");
	if( !xml.loadXML(rsString) )throw new Error(0,xml.parseError.reason);
	for( var fieldName in stringFieldSizes ){
		var node = xml.selectSingleNode("//s:AttributeType[@name='"+fieldName+"']");
		node.childNodes[0].setAttribute("dt:maxLength",stringFieldSizes[fieldName]);
	}
	var attrNodes = xml.selectNodes("//s:AttributeType[not(@rs:writeunknown)]");
	for( var i = 0; i < attrNodes.length; i++ )
		attrNodes[i].setAttribute("rs:writeunknown",true);
//	for( var i=0; i < aAttrs.length; i++ )
//		if( !aAttrs[i].match(/writeunknown/i) )
//			rsString = rsString.replace(aAttrs[i],aAttrs[i].substr(0,aAttrs[i].length-1)+" rs:writeunknown='true'>");
//	var strm = new ActiveXObject("ADODB.Stream");
//	strm.Open();	strm.WriteText(rsString);	strm.Position = 0;
	var rs = new ActiveXObject("ADODB.Recordset");
	rs.CursorType = adOpenStatic = rs.LockType = adLockOptimistic = 3;
	try{
		rs.Open(xml);
	}catch(e){
		for(var attrs=xml.documentElement.attributes; attrs.length; )
			 xml.documentElement.removeAttribute(attrs[0].name);
		try{
			var xmlRS = top.document.createElement("XML");
			top.document.body.appendChild(xmlRS);
			if( xmlRS.loadXML(xml.documentElement.xml) )
				try{rs = cloneRS(xmlRS.recordset);
				}catch(e){rs = xmlRS.recordset;}
			else throw e;
		}finally{
			xmlRS.parentElement.removeChild(xmlRS);
			xmlRS = null;
		}
	}
	return rs; // ================================================================================
	var root = new ActiveXObject("Microsoft.XMLDOM");
	if( !root.loadXML(rsString) )return false;
	rs.open(root);
	return rs;
}
function cloneRS(rs){
	if( rs.Fields(0).Name == "$Text" )return emptyRS();
	var isXmlRS = containsField(rs,"$Text");
	var rsNew = new ActiveXObject("ADODB.Recordset");
	for( var i=0; i < rs.Fields.Count; i++ )
		if( rs(i).Name != "$Text" )
			if( isXmlRS )rsNew.Fields.Append(rs(i).Name,200,512,adFldIsNullable=0x20);
			else{
				rsNew.Fields.Append(rs(i).Name,rs(i).Type,rs(i).DefinedSize,adFldIsNullable=0x20);
				var field = rsNew(i);
				field.Precision = rs(i).Precision;
				field.NumericScale = rs(i).NumericScale;
			}
	rsNew.Open();
	if( rs.Fields(0).Name != "$Text" && rs.recordCount > 0 )
		for( rs.MoveFirst(); !rs.EOF; rs.MoveNext() ){
			rsNew.AddNew();
			for( var i=0; i < rs.Fields.Count; i++ )
				if( rs(i).Name != "$Text" )
					rsNew(i).Value =  rs(i).Value;
		}
	return rsNew;
}
function emptyRS(){
	var rs = new ActiveXObject("ADODB.Recordset");
	rs.Fields.Append("$Empty",200,1,adFldIsNullable=0x20);
	rs.Open();
	return rs;
}
function loadDSO(el,source,sync,filter){
//var adcExecSync = 1,adcExecAsync = 2
	var newRS = true;
	var dataSrc = getDataSrc(el,true);
	if( source && source.indexOf("<") >= 0 ){
		if( typeof(filter) == "boolean" && filter ){
			filter = dataSrc.recordset.filter;
			dataSrc.recordset.filter = 0;
		}
		var rs = getRSFromString(source);
		newRS = !updateRS(dataSrc.recordset,rs);
		if( newRS )dataSrc.SourceRecordset = rs;
		if( filter )dataSrc.recordset.filter = filter;
	}else{
		dataSrc.FetchOptions = 3;//sync || 1;
		dataSrc.ExecuteOptions = sync || 1;
		dataSrc.URL = source || dataSrc.urlIn;
		if( dataSrc.URL.indexOf("/")==0 )dataSrc.URL = getScriptServer()+dataSrc.URL;
		dataSrc.Refresh();
	}
//	if( !sync )return;
	try{
		if( document.activeElement && document.activeElement.value != 'undefined' )
			document.activeElement.focus();
	}catch(e){}
	if( typeof(isRDSError)!='undefined' && isRDSError(dataSrc.recordset) )return false;
	if( newRS && dataSrc.table )showDSO(dataSrc,eval(dataSrc.table));
	return newRS;
///Locals
	function isRDSError_(rs,noShow){
		if( !rs || !rs.State || rs.RecordCount < 1 )return false;
		if( !rs.Fields(0).Name.match(/ErrorNumber/i) ) return false;
		if( !noShow )alert( "Error:"+rs(0).value+"\n"+rs(1).value );
		return true;
	}
}
//<table id="tblCreditInfo" >
//	<thead><tr><th></th></tr></thead>
//	<tbody><tr><td clone=" "><input dataFld="*" size="10"/></td></tr></tbody>
//</table>
if( false ){
var rs = new ActiveXObject("adodb.recordset");
}
function showDSO(dso,tblTempl,search){
	if( tblTempl.locked )return;
	if( !tblTempl )tblTempl = eval(dso.table);
	if( !tblTempl )return;
	if(tblTempl.tagName.match(/table/i))return showDSOTable(dso,tblTempl,search);
	if(tblTempl.tagName.match(/select/i))return showDSOSelect(dso,tblTempl);
}
function showDSOSelect(dso,sel){
	var rs = getDataSrcRS(dso);
	if( !rs )return setTimeout("showDSO("+dso.uniqueID+","+sel.uniqueID+")",1000);
	fillSelect(rs,sel);
}
function isXmlRSEmpty(xmlRS){
	if( typeof(xmlRS) == "string" )xmlRS = getRSFromString(xmlRS);
	return !xmlRS || xmlRS.state == 0 ||
				 xmlRS.recordCount == 1 && xmlRS.Fields.Count == 1 && xmlRS.Fields(0).Name == "$Text";
}
function fillSelect(rs,sel,text,value,defaultValue){
	if( text == undefined )text = sel.dataTxt;
	if (value == undefined) value = sel.dataVal;
	text = text || value;
	value = value || text;
	if (!value) value = text = sel.dataFld;
	while(sel.length) sel.options.remove(0);
	if( typeof(rs) == "string" )rs = getRSFromString(rs);
	if( !rs  || !rs.state || rs.RecordCount == 0 || isXmlRSEmpty(rs) )return;
	var hasStyle = containsField(rs,"style");
	var def = containsField(rs,"def");
	for( rs.MoveFirst() ; !rs.EOF; rs.MoveNext() ){
		var oOption = document.createElement("OPTION");
		if( hasStyle && rs("style").value )oOption.style.cssText = rs("style").value;
		sel.options.add(oOption);
		try{
		oOption.innerText = rs(text||sel.dataTxt).value === null ? "" : rs(text||sel.dataTxt).value;
		oOption.value = rs(value||sel.dataVal).value === null ? "" : rs(value||sel.dataVal).value;
		}catch(e){break;}
		continue;
		var option = new Option(rs(text||sel.dataTxt).value,rs(value||sel.dataVal).value);
		if( hasStyle && rs("style").value )option.style.cssText = rs("style").value;
		if( def && eval(rs("def").value) && arguments.length < 5 ) defaultValue = option.value;
		sel[sel.length] = option;
	}
	if(rs.RecordCount){
		rs.MoveFirst();
		if( defaultValue !== undefined )sel.value = defaultValue;
	}
	if( !sel._size )sel._size = sel.size;
	sel.size = Math.min(sel._size,Math.max(sel.length,2));
}
function getZs(rs){
	var Zs = new Array;
	if( !rs.recordCount )return '';
	for( var f=0; f < rs.Fields.Count; f++ ){
		var func = (rs.Fields(f).Name.match(/^(.{3})__/)||{})[1];
		if( !func )continue;
		switch( func ){
			case 'Sum': var aggr = __Sum(rs,rs.Fields(f).Name);break;
			case 'Avg': var aggr = __Avg(rs,rs.Fields(f).Name);break;
		}
		Zs.push(__formatAggr(rs.Fields(f).Name,aggr));
	}
	return Zs;
	//Local
	function __formatAggr(fieldName,aggr){
		var name = {func:fieldName.substr(0,1),name:fieldName.match(/[^_]+$/)};
		return name.name+"("+name.func+"):"+__formatNumber(aggr);
	}
	function __Sum(rs,fieldName){
		var sum = 0;
		if( containsField(rs,fieldName.split("__")[1]) )
			fieldName = fieldName.split("__")[1];
		for( rs.MoveFirst(); !rs.EOF; rs.MoveNext() )
			sum += rs.Fields(fieldName).value;
		return sum;
	}
	function __Avg(rs,fieldName){
		return Math.round(100*__Sum(rs,fieldName)/rs.recordCount)/100;
	}
	function __formatNumber(n){
		n = new Number(n);
		var s  = n.toLocaleString();
		return n >= 100 ? s.replace(/[.]\d\d$/,"") : s;
	}
}
                    // *********************
                    // **** Filter DSO *****
                    // *********************
function findSearchElement(table,fieldName){
	var searchEls = table.all.search;
	if( searchEls && !"length" in searchEls )searchEls = new Array(searchEls);
	for( var i=0; searchEls && i < searchEls.length; i++ )
		if( searchEls[i].field == fieldName )return searchEls[i];
	return null;
}
function filterDSO(txt){
	var table = getParentByTag(txt,"TABLE");
	var rs = getDataSrcRS(txt);
	rs.Filter = buildFilters(table,rs);
	var all = (table.caption||{}).all;
	//debugger;
	for( var i=0; all && i < all.length; i++ )
		if( (all[i].innerText||"").match(/\s\d+\s/) )
			all[i].innerHTML = all[i].innerHTML.replace(/\s\d+\s/," "+rs.recordCount+" ");
	if( !rs.recordCount || table.goFilter || searchCount(table) == 1 && (table||{}).onfilter ){
	 table.onfilter(table);
	 table.goFilter = false;
	}
	try{status = rs.recordCount+" items;"+getZs(rs);}catch(e){}
	return;
	var filter = txt.type=="checkbox" ? txt.checked : txt.value.replace(/[*]/g,"");
	var field = txt.field;
	if( rs.Filter && txt.filter){
		var normFilter = excludeFilter(table);
		rs.Filter = normFilter;// normalize(rs.Filter.replace(txt.filter,""));
	}
	if( filter ){
		txt.filterInfo = buildFilter(rs(field),filter);
		if( !txt.filterInfo )return false;
		txt.filter = txt.filterInfo.construct();
		try{
			rs.Filter = _OR_AND_OR(_OR(rs.Filter),_OR(txt.filter)).join(" OR\n");
		}catch(e){
			status = "Filter Error:"+_OR_AND_OR(_OR(rs.Filter),_OR(txt.filter))
			try{
				rs.Filter = (rs.Filter?rs.Filter+" AND ":'')+txt.filter;
			}catch(e){
				for( var sf=0; sf < search.length; sf++ )if( search[sf] != txt )search[sf].value = "";
				rs.Filter = txt.filter;
				status = "Filter Error";
			}
		}
		txt.title = "Filter:"+rs.Filter;
	}
	//var callOnFilter = fetch(table,txt);
	if( searchCount(table) == 1 && (table||{}).onfilter ){
	 table.onfilter(table);
	 //if( table.onfilter(table) === false )fetch(table);
	} 
	///Locals
	function buildFilters(table,rs){
		var sfs = table.all["search"];
		for( var sf=0,aORs=[]; sf < sfs.length; sf++ ){
			var txt = sfs[sf];
			if( !txt.value )continue;
			var text = txt.type=="checkbox" ? txt.checked : txt.value.replace(/[*]/g,"");
			var filter = buildFilter(rs(txt.field),text).construct();
			aORs = aORs.length ? _OR_AND_OR(aORs,_OR(filter)) : _OR(filter);
		}
		return aORs.join(" OR\n");
	}
	function excludeFilter(table){
		var sfs = table.all["search"];
		for( var sf=0,aORs=[]; sf < sfs.length; sf++ )
			if( sfs[sf] != txt && sfs[sf].value )
				aORs = aORs.length ? _OR_AND_OR(aORs,_OR(sfs[sf].filter)) : _OR(sfs[sf].filter);
		return aORs.join(" OR ");
	}
	function searchCount(table){
		for(var c=0,s=0,ss = table.all.search; s < ss.length; s++ )
			if( ss[s].value )c++;
		return c;
	}
	function fetch(table,txt){
	 if( arguments.length == 1 )return table.searchFields = null;// reset
	 var sf = table.searchFields || (table.searchFields=  new ArrayX(table));
	 if( txt.filter )sf.add(txt);
	 else sf.rem(txt);
  return sf.freeze();
  //alert("Fetch:"+ret+"\n"+sf.join(sf.base));
	 return ret;
	}
	function ArrayX(table){
	 this.fields = [];
	 this.add = function(e){if( this.index(e) < 0 )this.fields.push(e);}
	 this.rem = function(e){
	  var i = this.index(e);
	  if( i >= 0 )this.fields.splice(i,1);
	  return i;
	 }
	 this.index = function(e){
	  for( var i=0; i < this.fields.length; i++ )
	   if( this.fields[i] == e )return i;
	   return -1;
	 }
	 this.has = function(e){return this.find(e) >= 0;}
	 this.freeze = function(){
	  if( this.contains(this.base) )return false;
	  for( var i=0,a=[]; i < this.length(); i++ ){
	   this.fields[i]._Value = this.fields[i].value;
	   a.push(this.fields[i]);
	  }
	  return this.base = a;
	 }
	 this.length = function(){return this.fields.length;}
	 this.contains = function(a){
	  if( !a || !a.length || a.length > this.length() )return false;
	  for( var i=0; i < this.length(); i++ )
	   if( equals(a[0],this.fields[i]) )break;
   if( i == this.length() )return false;
	  for( var j=1 ; j < a.length; j++ )
	   if( !equals(a[j],this.fields[i+j]) )return false;
	  return true;
	  // Local
	  function equals(e1,e2){return e1 == e2 && e1.value.match(new RegExp("^"+e2._Value))}
	 }
	 this.join = function(a){
	  for( var i=0,ret=[]; i < a.length; i++ )
	   ret.push(a[i]._Value);
	  return ret.join(",");
	 }
	 for( var i=0; table && i < table.all.search.length; i++ )
	  if( table.all.search[i].value )this.add(table.all.search[i]);
	}
	function normalize(s){
		if( !s )return 0;
		s = s.replace(/^\s*and\s*/i,"").replace(/\s*and\s*$/i,"").replace(/\s+and\s+and/i," AND ");
		return s.replace(/^\s*OR\s+/i,"");
		//s.match(/^[()\s]*OR\s/i) ? "" : s;
	}
 function buildFilter(field,text){
	 var isNumeric = isDBNumeric(field.Type)
	 var filterInfo = new FilterInfo(field.Name);
	 text = trim(text+'');
	 if( text === "" || text === null )return null;
	 var q = isNumeric?"":"'";
	 var operand = isNumeric?"=":"like";
	 var ps = isNumeric?"":"*";//p(refix)s(uffix)
	 if( text.indexOf('~') >= 0 ){
		 var aFilter = text.split('~');
		 if( aFilter[0] )filterInfo.add(">=",aFilter[0],isNumeric);
		 var gt = aFilter[0]?"["+field.Name+"] >= "+q+aFilter[0]+q:'';
		 if( aFilter[1] )filterInfo.add("<=",aFilter[1],isNumeric);
		 var lt = aFilter[1]?"["+field.Name+"] <= "+q+aFilter[1]+q:'';
		 var filter = gt + ((gt && lt)?" AND ":'') + lt;
	 }else{
		 //if( isNumeric )filterInfo.type = "OR";
		 var aFilter = text.split(' ');
		 var aFilterOR = text.split('|');
		 if( aFilter.length > 1 && aFilterOR.length > 1 )
			return alert("Can't combine [AND] and [OR] conditions")||false;
		 if( aFilterOR.length > 1 ){
			 filterInfo.type = "OR";
			 aFilter = aFilterOR;
		 }
		 for( var i=0,aLike=[]; i < aFilter.length; i++ )
		  if( aFilter[i] ){
		   filterInfo.add(operand,ps+aFilter[i]+ps,isNumeric);
		   aLike.push("["+field.Name+"] "+operand+" "+q+ps+aFilter[i]+ps+q);
		  }
	 	 var filter = aLike.join(" "+filterInfo.type+" ",aLike);
	 }
		if( filterInfo.construct() != filter )
		 alert("Error while building filter:\n\n"+filterInfo.construct()+"\n"+filter);
		return filterInfo;
	 // Local 
	 function FilterInfo(fieldName){
		this.type = "AND";
	  this.fieldName = fieldName.indexOf("[") == 0 ? fieldName : "["+fieldName+"]";
	  this.filters = [];
	  this.length = function(){return this.filters.length}
	  this.add = function(operand,value,numeric){this.filters.push(new Info(operand,value,numeric));}
	  this.construct = function(){
	   for( var i = 0,a = []; i < this.filters.length; i++ )
	    a.push(this.filters[i].filter(this.fieldName));
	   return a.join(" "+this.type+" ");
	  }
	  this.toArray = function(){
	   for( var i=0,a=[]; i < this.length(); i++ )
	    a.push(this.filters[i].toArray(this.fieldName));
	    return a;
	  }
	  // Local
	  function Info(operand,value,numeric){
	   this.operand = operand;
	   this.value = value;
	   this.qoute = numeric ? "" : "'";
	   this.filter = function(fieldName){
	    return fieldName+" "+this.operand+" "+this.qoute+this.value+this.qoute;
	   }
	   this.toArray  = function(fieldName){return [fieldName,this.operand,this.value];}
 		}
	 }
 }
}
function _OR(s){
	if( !s )return [];
	return s.replace(/\s+OR\s+/gi,"\1").split("\1");
	/********************************************/
	var p = (s.match(/[)]+/g)||new Array).sort()
	var n = (p[p.length-1]||"").length;
	var sOR = "([(]{"+n+"}.+[)]{"+n+"})";
	var re  = new RegExp("[)]{"+n+"}\\s+OR\\s+[(]{"+n+"}","g");
	var nOR = (s.match(re)||new Array).length;
	var OR = "\\s+OR\\s+";
	for( var sRe=sOR; nOR--; sRe+=OR+sOR ){}
	var re = new RegExp(sRe);
	return (s.match(re) || new Array).slice(1);
	///Local
	function _repeat(s,n){
		for( var ss=""; n--; ss+=s){}
		return ss;
	}
}
function _OR_AND_OR(aOR1,aOR2){
	if( !aOR1.length )return aOR2;//.join(" OR ");
	for( var i=0,a=new Array; i < aOR2.length; i++ )
		a = a.concat(_OR_AND(aOR1,aOR2[i]));
	return a;//.join(" OR ");
}
function _OR_AND(aOR,sAND){
	if( !aOR || aOR.length == 0 )return sAND;
	if( !sAND )return aOR;
	for( var i=0,a=new Array; i < aOR.length; i++ )
		a.push("("+aOR[i]+" AND "+sAND+")");
	return a;//.join(" OR\n");
}
function isDBNumeric(fieldType){
	switch(fieldType){
		case 0: return true;
		case 2: return true;
		case 3: return true;
		case 4: return true;
		case 5: return true;
		case 6: return true;
		case 7: return true;
		case 8: return true;
		case 9: return true;
		case 10: return true;
		case 11: return true;
		case 13: return true;
		case 14: return true;
		case 16: return true;
		case 17: return true;
		case 18: return true;
		case 19: return true;
		case 20: return true;
		case 21: return true;
		case 64: return true;
		case 72: return true;
		case 128: return true;
		case 129: return false;
		case 130: return false;
		case 131: return true;
		case 132: return true;
		case 133: return true;
		case 134: return true;
		case 135: return true;
		case 136: return true;
		case 138: return true;
		case 139: return true;
		case 200: return false;
		case 201: return false;
		case 202: return false;
		case 203: return false;
		case 204: return true;
		case 205: return true;
	}
	return false;
}
function sortDSO(spn){
	var rs = getDataSrcRS(spn);
	var field = spn.field;
	if( !rs.Sort )return rs.Sort = buildSort(field,"asc");
	var aSort = rs.Sort.split(",");
	var aSorts = new Array;
	for( var i=0; i < aSort.length; i++ ){
		var m = aSort[i].match(/[[](.+)[]]\s+(.+)/);
		aSorts.push({fieldName:m[1],order:m[2]});
	}
	var index = findSortIndex(aSorts,field);
	if( index >= 0 ){
		if( index == 0 )reverseOrder(aSorts[index]);
		else aSorts.unshift(aSorts.splice(index,1)[0]);
		aSort = [];
		for( var i = 0; i < aSorts.length; i++ )
			aSort.push(buildSort(aSorts[i].fieldName,aSorts[i].order));
		rs.Sort = aSort.join(",");
	}else rs.Sort = buildSort(field,"asc")+","+rs.Sort;
	//status = rs.sort;
	///locals
	function buildSort(fieldName,order){return "["+fieldName+"] "+order;}
	function reverseOrder(oSort){
		oSort.order = oSort.order == "asc" ? "desc" : "asc";
	}
	function findSortIndex(aSorts,field){
		for( var i=0; i < aSorts.length; i++ )
			if( aSorts[i].fieldName == field )return i;
		return -1;
	}
}
var rowoverID;
function isHidden(field,oHiddens){
	return oHiddens && oHiddens[field.Name.toLowerCase()]!=null || field.Name.match(/^(Avg|Sum|Style)__/)
}
function showDSOTable(dso,tblTempl,search){
	if( !defined(search) )
		search = tblTempl.noSearch ? false : true;
	var rs = getDataSrcRS(dso);
	if( !rs )return setTimeout("showDSO("+dso.uniqueID+","+tblTempl.uniqueID+")",1000);
	var oFlds={},trSearch;
	var oHiddens = getHiddenFields(tblTempl);
	buildHeader(tblTempl.tHead,rs,oHiddens,false,eval(tblTempl.SELECTS));
	buildHeader(tblTempl.tFoot,rs,oHiddens,true,eval(tblTempl.SELECTS));
	var tr = tblTempl.tBodies[0].rows[0];
	var clone = selectElementsByAttributeEx(tr,"clone")[0];
	var readOnlyElement = selectElementsByAttributeEx(tr,"dataFld","R[*]O")[0] || null;
	var aFlds = selectElementsByAttributeEx(tr,"dataFld");
	if( aFlds.length == 0 )return alert("No elements with \"dataFld\" attribute found.");
	for( var f=0; f < aFlds.length; f++ )
		if( aFlds[f].dataFld )oFlds[aFlds[f].dataFld.toLowerCase()] = true;
	aFlds = selectElementsByAttributeEx(clone,"dataFld","[*]");
	for( var f=0; aFlds && aFlds.length && f < rs.Fields.Count; f++ ){
		if( oFlds[rs.Fields(f).name.toLowerCase()] || isHidden(rs.Fields(f),oHiddens) )continue;
		if( isReadOnly(tblTempl,rs(f)) && readOnlyElement ){
			readOnlyElement.dataFld = rs(f).Name;
			tr.insertBefore(getParentTD(readOnlyElement).cloneNode(true),clone)
			continue;
		}
		aFlds[0].dataFld = rs.Fields(f).name;
		tr.insertBefore(changeInputType(clone.cloneNode(true),rs,rs.Fields(f).Name,eval(tblTempl.SELECTS)),clone);
	}
	if( clone )clone.removeNode(true);
	if( readOnlyElement )getParentTD(readOnlyElement).removeNode(true);
	var aFlds = selectElementsByAttributeEx(tr,"dataFld",/.+/);
	for( var f=0; f < aFlds.length; f++ )
		if( isDBNumeric(rs.Fields(aFlds[f].dataFld).Type) )getParentTD(aFlds[f]).align = "right";
	tblTempl.dataSrc = "#"+dso.id;
	if(rs.RecordCount)rs.MoveFirst();
	if( tblTempl.style.display.match(/none/i) )tblTempl.style.display = "";
	if( rs.RecordCount && tblTempl.rowover ){
		rowoverID = tblTempl.addBehavior("include/rowover_js.htc");
	}
	// Locals
	function changeInputType(parent,rs,fieldName,selects){
		var field = rs(fieldName);
		if( field.Type == (adBoolean = 11) && parent.all.tags("INPUT").length ){
			var input = parent.removeChild(parent.all.tags("INPUT")[0]);
			parent.insertAdjacentHTML("beforeend",input.outerHTML.replace(">"," type='checkbox'>"));
			parent.width="1%";
		}
		if( selects && selects[field.name.toLowerCase()] ){
			var input = parent.removeChild(parent.all.tags("INPUT")[0]);
			parent.insertAdjacentHTML("beforeend",input.outerHTML.replace(/^<input/i,"<select style='width:auto' ")+selects[field.name.toLowerCase()]+"</select>");
		}
		var styleFieldName = "Style__"+fieldName;
		if( containsField(rs,styleFieldName) )
			parent.lastChild.style.cssText += ";"+rs(styleFieldName);
		return parent;
	}
	function isReadOnly(tbl,field){
		var oReadOnly = getReadOnlyFields(tbl);
		return oReadOnly && defined(oReadOnly[field.Name.toLowerCase()]);
	}
	function getHiddenFields(tbl){
		var o = getFieldsFromList(tbl,"hiddenFields");
		o["$text"] = "";
		return o;
	}
	function getReadOnlyFields(tbl){return getFieldsFromList(tbl,"readOnlyFields");}
	function getFieldsFromList(tbl,listName){
		var list = tbl.getAttribute(listName);
		if( !list )return {};
		var aFields = list.split(",");
		var oFields = {};
		for( var i=0; i < aFields.length; i++ ){
			var name = aFields[i].split('|')[0].toLowerCase();
			var format = aFields[i].split('|')[1]||'';
			oFields[name] = format;
		}
		return oFields;
	}
	function buildHeader(tHead,rs,hiddenFields,footer,selects){
		if( !tHead )return;
		if( footer == undefined )footer = tHead.tagName.toUpperCase() == "TFOOT";
		for( var i=0,tr,clone; i < tHead.rows.length; i++ ){
			tr = tHead.rows[i];
			var thClone = getChildByAttr(tr,"clone");
			if( !thClone )return;
			var thBefore = thClone ? tr.cells[thClone.cellIndex+1]||null : null;
			thClone = thClone.removeNode(true);
			for( var f=0; f < rs.Fields.Count; f++ )
				if( footer && isReadOnly(tHead.parentElement,rs(f)) && !(selects||{})[rs(f).Name.toLowerCase()] )
					tr.insertBefore(document.createElement("TD"),thBefore);
				else if( !isHidden(rs.Fields(f),hiddenFields) ){
					var newEl = thClone.cloneNode(true);
					var cell = tr.insertBefore(footer?changeInputType(newEl,rs,rs.Fields(f).Name,footer?selects:null):newEl,thBefore);
					cell.fieldName = rs.Fields(f).Name;
					if( !footer )cell.innerHTML = makeSort(rs.Fields(f))+(search?"<br>"+makeSearch(rs.Fields(f),selects):"");
					var sel = cell.all.tags("SELECT");
					if( sel.length )sel[0].selectedIndex = -1;
				}
		}
	}
	function makeSort(field){
		return "<span onclick='sortDSO(this)' field='"+field.name+"' id='sort' style='cursor:hand' title='Click here to sort by this column'>"+field.Name+"</span>";
	}
	function makeSearch(field,selects){
		var onChange = "onchange",type="text";
		if( field.Type == (adBoolean = 11) ){
			onChange = "onclick"; type = "checkbox";
		}
		var s = "<input style='width:100%;padding-right:10px;background-color:LightYellow;color:navy;overflow-y:visible' class='dsoSearch' field='"+field.name+"' "+onChange+"='return filterDSO(this)' id='search' type='"+type+"'>";
		if( selects && selects[field.name.toLowerCase()] ){
			s = s.replace(/^<input/i,"<select")+"<OPTION>"+selects[field.name.toLowerCase()]+"</select>";
		}
		return s;
	}
	function selectElementsByAttribute(node,attrName,attrValue){
	var aFlds = new Array();
		for(var i=0; node && i < node.all.length; i++ )
			if( node.all[i].tagName != "OPTION" && defined(node.all[i][attrName]) && 
					(!defined(attrValue) || node.all[i][attrName] == attrValue) )
				aFlds[aFlds.length] = node.all[i];
		return aFlds;
		function defined(v){return typeof(v) != 'undefined'}
	}
}
function reloadXMLDSO(xmlObject,xmlText){
	setTimeout(function(){_foo()},100);
	// Local
	function _foo(){
		if( loadXML(xmlObject,xmlText) )return false;
		setTimeout(function(){try{xmlObject.document.activeElement.select()}catch(e){}},100);
	}
}
function updateXmlDSO(xmlDSO,rsString,tableObject){
	if( updateRS(xmlDSO.recordset,getRSFromDS(rsString)) )return 1;
	var ret = loadXML(xmlDSO,rsString) ? 0 : -1;
	if( tableObject ){
		tableObject.dataSrc = tableObject.dataSrc.replace("#",'');
		xmlDSO.loadXML(rsString);
		if( tableObject.dataSrc.indexOf("#") != 0 )tableObject.dataSrc = "#" + tableObject.dataSrc;
	}
	return ret;
}
function updateAdoDSO(dso,rs){
	if( typeof(rs) == "string" )rs = getRSFromString(rs);
	if( !updateRS(getDataSrcRS(dso),rs) )dso.sourceRecordset = rs;
}
function updateRS(rsDest,rsSrc){
	if( typeof(rsSrc) == "string" )rsSrc = getRSFromString(rsSrc);
	if( !rsDest || !rsSrc )return false;
	try{var ap = rsDest.AbsolutePosition;}catch(e){return false;}
	if( compareRSs(rsDest,rsSrc) !== 0 )return false;
	if( rsDest.recordCount )rsDest.MoveFirst();
	if( rsSrc.recordCount )rsSrc.MoveFirst();
	for( ; !rsDest.EOF && !rsDest.BOF && !rsSrc.EOF && !rsSrc.BOF; rsDest.MoveNext(),rsSrc.MoveNext() )
		for( var i=0; i < Math.min(rsDest.Fields.Count,rsSrc.Fields.Count); i++ )
			if( /*rsDest.Fields(i).Value != rsSrc.Fields(i).Value &&*/ rsSrc.Fields(i).Name != "$Text" && rsDest.Fields(i).Name != "$Text" )
				rsDest.Fields(i).Value = rsSrc.Fields(i).value != null ?rsSrc.Fields(i).Value : (isDBNumeric(rsSrc(i).Type)?0:"");
	deleteRsRecords(rsDest,rsSrc);
	if( rsSrc.recordCount > rsDest.recordCount )addRsRecords(rsDest, rsSrc);
	if( rsDest.recordCount )rsDest.MoveFirst();
	return true;
	// Locals
	function compareRSs(rs1,rs2){
		var rc1 = rs1.Fields.Count - (rs1(rs1.Fields.Count-1).Name == "$Text" ? 1 : 0);
		var rc2 = rs2.Fields.Count - (rs2(rs2.Fields.Count-1).Name == "$Text" ? 1 : 0);
		for( var f=0,same=true; rc1 == rc2 && f < rc1; f++ )
			if( rs1.Fields(f).Name != rs2.Fields(f).Name )return false;
		return rc1 == rc2 ? 0 : (rc1 > rc2 ? 1 : -1);
	}
	function fieldCount(rs){
		for( var i=0,j=0; i < rs.Fields.Count; i++ )
			if( !rs.Fields(i).Name.match(/:/) && rs.Fields(i).Name != "$Text" )j++
		return j;
	}
	function deleteRsRecords(rsDest,rsSrc){
		while(rsDest.recordCount > ((rsSrc||{}).recordCount||0) ){
			rsDest.MoveLast();
			rsDest.Delete();
		}
	}
	function addRsRecords(rsDest,rsSrc){
		var fcDest = fieldCount(rsDest);
		var fcSrc  = fieldCount(rsSrc);
		for(rsSrc.absolutePosition = rsDest.recordCount + 1; !rsSrc.EOF; rsSrc.MoveNext() ){
			rsDest.addNew();
			for(var i=0; i < fcSrc && i < fcDest; i++)
				if( rsSrc.Fields(i).value != null )rsDest.Fields(i).value = rsSrc.Fields(i).value;
		}
	}
}
function containsField(rs,fieldName){
	var re = new RegExp("^"+fieldName+"$","i");
	for( var i = 0; i < rs.Fields.Count; i++ )
		if( re.test(rs.Fields(i).Name) )return true;
}
function getDataSrcrs(el){return getDataSrcRS(el);}
function getDataSrcRS(el){
	if( el.tagName == "OBJECT" )return el.recordset;
var _dsO_ = getDataSrc(el);
	if( _dsO_ == "" )return null;
	return el.document.all[_dsO_].recordset;
}
function getDataSrcObj(el){	return eval(getDataSrc(el)) || null }
function getDataSrc(el,returnObject){
	if( el && 
			(el.classid && el.classid.match(/clsid:BD96C556-65A3-11D0-983A-00C04FC29E33/i) ||
			 el.tagName == "XML"
			)
		)return returnObject ? el : el.id;
	for( var src = "" ; el && !src; el = el.parentElement )
		try{src = el.dataSrc || el.getAttribute("DataSource") || "";}catch(e){}
	if( src )return returnObject ? el.document.all[src.substr(1)] : src.substr(1);
	throw new Error(0,"No parent element with Data Source was found.");
}
function getDirtyStatus(el){
var dso = getDataSrcObj(el);
	return dso && dso.dirty ? true : false;
}
function setDirtyStatus(el,value){
var dso = getDataSrcObj(el);
	if( dso )dso.dirty = value || "";
}
//Events
function onInputKeyPress(){return;
	var rs = getDataSrcRS(event.srcElement);
	if( event.srcElement.recordNumber )
		rs.absolutePosition = event.srcElement.recordNumber;
	rs(event.srcElement.dataFld).value = event.srcElement.value;
	setDirtyStatus(event.srcElement,1);
}
function showCompliteDSO(el){
	var rs = getDataSrcRS(el);
	if( !rs || rs.state != 1 )return;
	if( el.readyStateValue != 4 )return;
	el.style.visibility = "visible";
}
function openHttpRS(path){
	var rs = new ActiveXObject("adodb.recordset");
	rs.Open(path);
	return isErrorEx(rs,false,openHttpRS.caller)?null:rs;
}
function findRowByFieldValue(rs,field,value){//return 0-based position or -1
	rs.MoveFirst();
	rs.Find(field+" = "+value);
	return rs.EOF ? -1 : rs.AbsolutePosition - 1;
}
function filterRS(rsFoo,fieldName,filter){
	var rs = typeof(rsFoo) == "function" ? rsFoo() : rsFoo;
	if( !rs.recordCount )return rs;
	for( rs.MoveFirst(); !rs.EOF && !rs.BOF; )
		if( rs(fieldName).value == filter )rs.MoveNext();
		else rs.Delete();
	if( !rs.recordcount )
		return alert("ATTANTION!\n\nEmpty record in "+getFuncName(arguments.callee.caller)+"!");
	rs.MoveFirst();
	return rs;
}
// ----------------- DataSet ------------------
function getDSfromRS(rs,name,fieldName,fieldValue){return getDSFromRS(rs,name,fieldName,fieldValue)}
function getDSFromRS(rs,name,fieldName,fieldValue){// ADO.NET DataSet from ADO Recordset
	if( isXmlRSEmpty(rs) )return "";
	var root;
	if( name ){
		if( document.all[name] )
			document.all[name].parentElement.removeChild(document.all[name]);
		root = document.createElement("XML");
		root.id = name;
		document.body.appendChild(root);
	}else	root = new ActiveXObject("Microsoft.XMLDOM");
	var dataSet = xmlAddElement(root,"DataSet");
	var currentRecord = rs.absolutePosition > 0 || _status(rs) == 1; 
	if( rs.recordCount ){
		if( !currentRecord )rs.MoveFirst();
		for(  ; !rs.EOF; rs.MoveNext() ){
			var dataTable = xmlAddElement(dataSet,"Table");
			for( var i = 0; i < rs.Fields.Count; i++ )
				if( rs.Fields(i).Name != "$Text" && rs.Fields(i).Value !== null && rs.Fields(i).Value !== undefined )
					xmlAddElement(dataTable,rs.Fields(i).Name).text =
						typeof rs(i).Value == "date" ?
							new Date(rs(i).Value).toDateString() :
							(rs.Fields(i).Name.match(new RegExp(fieldName+'',"i"))?fieldValue:rs.Fields(i).Value)+'';
			if( currentRecord )break;
		}
	}
	return root;
	// Locals
	function _status(rs){try{return rs.status}catch(e){return 0}}
}
function getTableFromDS(xml,tableName){
	var root = new ActiveXObject("Microsoft.XMLDOM");
	if( !root.loadXML(xml) )throw new Error(0,root.parseError.reason);
	var rows = root.selectNodes("*/"+tableName);
	for( var sRS="",i=0; i < rows.length; i++ )
		sRS += rows[i].xml;
	return "<RS>"+sRS+"</RS>";
}
function getRSFromDS(text,tableName,refresh){return getRSfromDS(text,tableName,refresh)}
function getRSfromDS(text,tableName,refresh){
	var doc = document;
	if( refresh == undefined )refresh = true;
	var xmlName = "_XML_"+tableName;
	var xml = doc.all[xmlName];
	if( xml && !refresh )return xml.recordset;
	if( typeof(text) == "object" ){
		doc = text.document || doc;
		xml = text.xml || xml;
		text = text.text;
	}
	if( !xml )xml = createXMLElement(xmlName,doc);
	if( !xml.loadXML(text) )throw new Error(0,xml.parseError.reason);
	if( tableName ){
		if( !containsField(xml.recordset,tableName) ){
			var nodes = xml.selectNodes("*/*");
			if( nodes.length && nodes[0].nodeName.toLowerCase() == tableName.toLowerCase() )
				return _initRS(xml.recordset);
			return null;
		}
		return _initRS(xml.recordset(tableName).Value);
	}else return _initRS(xml.recordset);
	// Local
	function _initRS(rs){if(rs.recordCount>1)try{rs.MovePrevious()}catch(e){};return rs;}
	//*************************************//
	var root = new ActiveXObject("Microsoft.XMLDOM");
	if( !root.loadXML(text) )throw new Error(0,root.parseError.reason);
	if( !root.documentElement.childNodes.length )return null;
	
	xml = createXMLElement(xmlName);

	if( tableName || loadXML(xml,text) ){
		var rows = root.selectNodes("*/"+tableName);
		for( var sRS="",i=0; i < rows.length; i++ )
			sRS += rows[i].xml;
		if( !xml.loadXML("<ROWS>"+sRS+"</ROWS>") )throw new Error(0,xml.parseError.reason);
	}
	return xml.recordset;
}
// --------------------------------------------------------------------

function rsFind(elOrRS,fieldName,filter,valueField){
	var rs = typeof(elOrRS.absolutePosition) != 'undefined' ? elOrRS : null;
	if( !rs )rs = rsFromElement(elOrRS);
	if( !rs.recordCount )return null;
	for( rs.MoveFirst(); !rs.EOF && !rs.BOF; rs.MoveNext() )
		if( (rs(fieldName).value+"").match(filter) )break;
	if( rs.absolutePosition < 1 )return null;
	if( valueField )return rs(valueField).value;
	var tr = getParentTable(elOrRS).tBodies[rs.absolutePosition-1].rows[0];
	return tr;
}
function rsField(el,fieldName){
	if( arguments.length < 2 )
		fieldName = getFuncName(arguments.callee.caller).replace(/^_/,'');
	var rs = el.recordset || rsFromElement(el||getChildByAttr(null,"dataFld",fieldName));
	if( rs.Fields(0).Name == "$Text" )return null;
	return rs.Fields(fieldName);
}
function rsFromElement(el,position){
	var tr = getParentTR(el);
	var dsHolder = getParentByAttr(el,"dataSrc",".+");
	var table = _isTable(dsHolder) ? dsHolder : {};
	var rs = table.dataFld ? rsFromElement(table.parentElement,position) : getDataSrcRS(dsHolder);
	if( table.dataFld )rs = rs.Fields(table.dataFld).value;
	if( typeof(position) == "number" )
		rs.absolutePosition = position;
	else
		if( rs.recordCount && tr && tr.recordNumber != null && (position == undefined || position === true) )
			if( !tr.recordNumber )throw new Error(0,"RecordNumber["+tr.recordNumber+"] is not correct!");
			else rs.absolutePosition = tr.recordNumber;
	return rs;
	// Locals
	function _getDataSrc(el){return (el.dataSrc || el.getAttribute("DataSource")).substr(1);}
	function _isTable(el){return el.tagName == "TABLE"}
}
